﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Tiens.NotificationHub.Constant;
using Tiens.NotificationHub.Core.Options;
using Tiens.NotificationHub.Core.Services;

namespace Tiens.NotificationHub.Core
{
    public class UserAuthorizationHandler : AuthorizationHandler<UserRequirement>
    {
        private readonly IHostEnvironment _hostEnvironment;
        private readonly MockOptions _mockOptions;
        private readonly InMemoryTokenManager _tokenManager;

        public UserAuthorizationHandler(IHostEnvironment hostEnvironment,
            IOptions<MockOptions> mockOptions,
            InMemoryTokenManager tokenManager)
        {
            _hostEnvironment = hostEnvironment;
            _mockOptions = mockOptions.Value;
            _tokenManager = tokenManager;
        }

        protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context,
            UserRequirement requirement)
        {
            if (context.Resource is DefaultHttpContext httpContext)
            {
                string userId;
                if (_hostEnvironment.IsDevelopment())
                {
                    userId = _mockOptions.UserId;
                }
                else
                {
                    var token = httpContext.Request.Cookies[CookieConstant.Cookie];
                    userId = await _tokenManager.UserIdAsync(token.Trim('"'));
                }

                if (string.IsNullOrWhiteSpace(userId))
                {
                    context.Fail();
                    return;
                }

                httpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, userId) }));

                if (httpContext.User.HasClaim(x => x.Type == requirement.ClaimType))
                {
                    context.Succeed(requirement);
                    return;
                }
            } 
            
            context.Fail();
        }
    }
}
